<?php
namespace Tbf\Bundle\TbfBundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Tbf\Component\FileSystem\FileSystemFunction;

/**
* 这个di配置暂时全部使用php配置.
* 了解php配置di的使用方法
*/
class TbfExtension extends Extension
{
    public function load(array $configs, ContainerBuilder $container)
    {
        $configuration = new Configuration();
        $config = $this->processConfiguration($configuration,$configs);
        if (!empty($config['database'])) {
            $this->loadDb($config['database'],$container);
        }

        $this->loadBaseClass($container);
        $this->loadHtmlPurifier($container);
        $this->loadTbfMailer($container);
        $this->loadTbfAnnotationsReader($container);

        if (!$container->hasParameter('web_url')) {
            $container->setParameter('web_url','');
        }
        $container->setDefinition('tbf.test_kernel_factory',
            new Definition('Tbf\Bundle\TbfBundle\Service\SymfonyKernelFactory'))
            ->addArgument('test')
            ->addArgument(true);

        $container->setDefinition('tbf.listener.errors_logger',
            new Definition('Tbf\Bundle\TbfBundle\Error\ErrorsLoggerListener'))
            ->addArgument(new Reference('logger'))
            ->addArgument($container->getParameter('kernel.debug'))
            ->addTag('kernel.event_subscriber')
            ->addTag('monolog.logger',array('channel'=>'error'));

        $container->setDefinition('tbf.listener.exception_logger',
            new Definition('Tbf\Bundle\TbfBundle\Exception\ExceptionLoggerListener'))
            ->addArgument(new Reference('logger'))
            ->addTag('kernel.event_subscriber')
            ->addTag('monolog.logger',array('channel'=>'exception'));

        $this->addClassesToCompile(array_values($container->getParameter('kernel.bundles')));
        $this->addClassesToCompile(array(
            'Tbf\Bundle\TbfBundle\Controller\TbfController',
            'Symfony\Bundle\FrameworkBundle\Controller\Controller',
            'Tbf\Bundle\TbfBundle\Exception\BusinessException',
            'Tbf\Bundle\TbfBundle\Error\ErrorsLoggerListener',
            'Tbf\Bundle\TbfBundle\Exception\ExceptionLoggerListener'
        ));
    }

    public function loadBaseClass(ContainerBuilder $container)
    {
        $container->setDefinition('tbf.container_aware',
            new Definition())
            ->setAbstract(true)
            ->addMethodCall('setContainer',array(
                new Reference('service_container')));

        $container->setDefinition('tbf.container_construct',
            new Definition())
            ->setAbstract(true)
            ->addArgument(new Reference('service_container'));

        $container->setDefinition('tbf.model',
            new Definition('Tbf\Model\Model'))
        ->setAbstract(true)
        ->addMethodCall('setContainer',array(
            new Reference('service_container')));

        $container->setDefinition('tbf.event_dispatcher',
            new Definition('Symfony\Component\EventDispatcher\EventDispatcher'))
            ->setAbstract(true);

        if (!$container->hasDefinition('tbf.clock')) {
            $container->setDefinition('tbf.clock',
                new Definition('Tbf\Component\DateTime\Clock\SystemClock')
            );
        }
    }
    public function loadEvent(ContainerBuilder $container)
    {
        $container->setDefinition('tbf.listener.business_exception_listener',
            new Definition('Tbf\Listener\BusinessExceptionListener'))
            ->addTag('kernel.event_subscriber');
    }
    public function loadDb($config,ContainerBuilder $container)
    {
        $container->setParameter('tbf.config.database',$config);
    }
    public function loadHtmlPurifier(ContainerBuilder $container)
    {
        if (!class_exists('\HTMLPurifier')) {
            return;
        }
        $cache_path = $container->getParameter('kernel.cache_dir').'/html_purifier/serializer';
        FileSystemFunction::mkdir($cache_path);
        $container->setDefinition('tbf.html_purifier',
             new Definition('HTMLPurifier')
        )->addArgument(array(
                'Cache.SerializerPath'=>$cache_path,
                'Cache.SerializerPermissions'=>0777
        ))
        ->setLazy(true)
        ;
    }
    public function loadTbfMailer(ContainerBuilder $container){
        if (!class_exists('\Swift_Mailer')){
            return;
        }

        if ($container->hasParameter('mailer_user')){
            $default_sender = $container->getParameter('mailer_user');
        }else{
            $default_sender = '';
        }
        $container->setDefinition('tbf.mailer',
            new Definition('Tbf\Bundle\TbfBundle\Service\Mailer'))
            ->addArgument(new Reference('mailer',ContainerInterface::NULL_ON_INVALID_REFERENCE))
            ->addArgument($default_sender);
    }
    public function loadTbfAnnotationsReader(ContainerBuilder $container){
        if (!class_exists('\Doctrine\Common\Annotations\IndexedReader')){
            return;
        }
        $container->setDefinition('tbf.annotation_reader',
            new Definition('Tbf\Bundle\TbfBundle\Service\AnnotationsReader'))
            ->addArgument(new Reference('annotation_reader'));
    }
}
